<?php

/**
 * File upload class
 * @author ReGeDa
 */
class FileUpload extends Plugin_Object {

	/**
	 * Folder for storage files
	 * @var string
	 */
	protected $storage_dir;

	/**
	 * Max file size
	 * @var string
	 */
	private $max_filesize;

	/**
	 * Allowed file types
	 * @var array
	 */
	private $allowed_ftypes = array();

	/**
	 * Last upload error
	 * @var string
	 */
	private $last_error = NULL;

	/**
	 * MIME types
	 * @var array
	 */
	private $mime_types = array();

	/**
	 * Constructor
	 */
	public function __construct() {
		parent::__construct();
		$this->config('upload');
		// config from Platcode
		platcode()->plugins->include_class('static/Bytes');
		platcode()->lang->load('upload');
		platcode()->config->import('mime_types', $this->mime_types);
		// fetch PHP config
		$this->max_filesize = Bytes::from_option(ini_get('upload_max_filesize'));
	}

	/**
	 * Get persistant plugin state
	 * @override
	 * @return boolean
	 */
	public function is_persistant() {
		return TRUE;
	}

	/**
	 * Set storage folder
	 * @param string $dir
	 */
	public function set_storage_dir($dir) {
		$this->storage_dir = $dir;
	}

	/**
	 * Set allowed file types
	 * @param array|string $types 
	 */
	public function set_allowed_ftypes($types = NULL) {

		if (is_string($types))
			$types = preg_split('/\|/', $types, -1, PREG_SPLIT_NO_EMPTY);

		$this->allowed_ftypes = $types;
	}

	/**
	 * Fetch last error
	 * @return string
	 */
	public function get_last_error() {
		return $this->last_error;
	}

	/**
	 * Get error message
	 * @param number $code
	 * @return string
	 */
	private function error_message($code) {
		switch($code) {
			case UPLOAD_ERR_INI_SIZE:
			case UPLOAD_ERR_FORM_SIZE: return sprintf(lang('upload_err_max_size'), $this->max_filesize);
			case UPLOAD_ERR_PARTIAL: return lang('upload_err_partial');
			case UPLOAD_ERR_NO_FILE: return lang('upload_err_no_file');
			case UPLOAD_ERR_NO_TMP_DIR: return lang('upload_err_no_tmp_dir');
			case UPLOAD_ERR_CANT_WRITE: return lang('upload_err_cant_write');
			case UPLOAD_ERR_EXTENSION: return lang('upload_err_extension');
		}
	}

	/**
	 * Check allowed file type
	 * @param string $filename
	 * @return boolean|string
	 */
	private function check_allowed_ftypes($filename) {

		$mime = mime_content_type($filename);

		if ( ! empty($this->allowed_ftypes)) {

			foreach($this->allowed_ftypes as $type) {
				if ($this->mime_types[$type] == $mime)
					return $mime;
			}

			// has an error
			$this->last_error = lang('upload_err_denied_ftype');
			return FALSE;
		}
		// all types allows
		return $mime;
	}

	/**
	 * Do upload
	 * @param string $field
	 * @param FileUploadProcessor $processor
	 * @return boolean|array
	 */
	public function run($field, $processor = NULL) {

		// is upload
		if (isset($_FILES[$field])) {

			// check embedded upload error
			if ($_FILES[$field]['error'] == 0) {

				// check allowed file types
				$mime = $this->check_allowed_ftypes($_FILES[$field]['tmp_name']);

				if ($mime) {

					// create a new file name with destination folder
					$filename = $this->storage_dir.md5_file($_FILES[$field]['tmp_name']);

					// move a temporary file to destination
					if (move_uploaded_file($_FILES[$field]['tmp_name'], $filename)) {

						// use processor
						if ( ! is_null($processor)) {
							// process upload file
							if ($processor->file($filename, $_FILES[$field]['name'], $_FILES[$field]['size'], $mime))
								unlink($filename);
								
							return TRUE;
						}
						// return upload file parameters
						else {
							return array(
								'path' => $filename,
								'origname' => $_FILES[$field]['name'],
								'size' => $_FILES[$field]['size'],
								'mime' => $mime
							);
						}
					}
					else {
						// remove a temporary file
						unlink($_FILES[$field]['tmp_name']);
						$this->last_error = lang('upload_err_move_file');
					}
				}
			}
			else
				$this->last_error = $this->error_message($_FILES[$field]['error']);
		}
		// failure uploading
		return FALSE;
	}
}

// end of file